package com.qys.livesMall.app.user.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.qys.livesMall.app.user.event.UserFriendEvent;
import com.qys.livesMall.app.user.mapper.AppUserConcernMapper;
import com.qys.livesMall.app.user.mapper.AppUserFriendMapper;
import com.qys.livesMall.app.user.mapper.H2AppUserMapper;
import com.qys.livesMall.app.user.model.dto.AppBaseDTO;
import com.qys.livesMall.app.user.model.dto.sys.UserFriendEventDTO;
import com.qys.livesMall.app.user.model.entity.AppUserConcern;
import com.qys.livesMall.app.user.model.entity.H2AppUser;
import com.qys.livesMall.app.user.model.vo.app.AppUserConcernVO;
import com.qys.livesMall.app.user.service.AppUserConcernService;
import com.qys.livesMall.app.user.utils.TencentCloudIm;
import com.qys.livesMall.cache.RedisCache;
import com.qys.livesMall.common.constants.Constants;
import com.qys.livesMall.common.exception.QysException;
import com.qys.livesMall.common.utils.MessageUtils;
import com.qys.livesMall.framework.utils.SecurityUtils;
import com.qys.livesMall.framework.view.BaseQuery;
import com.qys.livesMall.open.enums.PushMessageTypeEnum;
import com.qys.livesMall.open.modal.dto.app.PushUserDeviceContentDTO;
import com.qys.livesMall.open.modal.dto.mail.PushTitleDTO;
import com.qys.livesMall.open.modal.dto.mail.PushUserDeviceDTO;
import com.qys.livesMall.open.service.PushUserDeviceService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * <p>
 * 用户关注列表 服务实现类
 * </p>
 *
 * @author
 * @since 2023-06-02
 */
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@Slf4j
public class AppUserConcernServiceImpl extends ServiceImpl<AppUserConcernMapper, AppUserConcern> implements AppUserConcernService {

    private final H2AppUserMapper userMapper;
    private final ApplicationContext applicationContext;
    private final AppUserFriendMapper userFriendMapper;
    private final PushUserDeviceService pushUserDeviceService;
    private final RedisCache redisCache;
    private final TencentCloudIm tencentCloudIm;
    /**
     * 用户关注/取消关注
     *
     * @param concernId 被关注人Id
     * @param userId    关注人id
     */
    @Override
    public synchronized void concernByUserId(Long concernId, Long userId) {
        QueryWrapper<AppUserConcern> wrapper = Wrappers.<AppUserConcern>query()
                .eq("user_Id", userId)
                .eq("concern_id", concernId);
        AppUserConcern userConcern = baseMapper.selectOne(wrapper);

        int status=0;
        if (null == userConcern) {
            H2AppUser concern = userMapper.selectById(concernId);
            if (null == concern) {
                throw new QysException(MessageUtils.message("user.not.found"));
            }

            userConcern = new AppUserConcern();
            userConcern.setConcernTime(LocalDateTime.now());
            userConcern.setConcernId(concernId);
            userConcern.setUserId(userId);
            userConcern.setStatus((byte) 1);
            status=1;
            userConcern.setAvatar(concern.getAvatar());
            userConcern.setNickName(concern.getNickName());
            baseMapper.insert(userConcern);
        } else {
            userConcern.setStatus((byte) (userConcern.getStatus() == 1 ? 0 : 1));
            userConcern.setConcernTime(LocalDateTime.now());
            status=userConcern.getStatus();
            baseMapper.update(userConcern, wrapper);
        }

        //添加好友
        UserFriendEventDTO dto = new UserFriendEventDTO();
        dto.setUserId(userId);
        dto.setFriendId(concernId);
        dto.setConcern(userConcern.getStatus() == 1);
        applicationContext.publishEvent(new UserFriendEvent(dto));

        if (status==1){
            H2AppUser user = userMapper.selectById(userId);
            PushUserDeviceDTO pushUserDeviceDTO=new PushUserDeviceDTO();
            pushUserDeviceDTO.setUserIds(Arrays.asList(concernId));

            PushTitleDTO pushTitleDTO=new PushTitleDTO();
            pushTitleDTO.setChinese(user.getNickName()+"关注了你");
            pushTitleDTO.setEnglish(user.getNickName()+"has followed you");
            pushUserDeviceDTO.setTitle(pushTitleDTO);

            PushUserDeviceContentDTO content=new PushUserDeviceContentDTO();
            content.setType(PushMessageTypeEnum.CONCERN);
            JSONObject json = new JSONObject();
            json.putOnce("userid",userId);
            json.putOnce("avatar",user.getAvatar());
            json.putOnce("nickName",user.getNickName());
            content.setData(json.toString());
            pushUserDeviceDTO.setContent(content);
            pushUserDeviceService.pushUserDevice(pushUserDeviceDTO);
        }

        //执行直播间禁言/取消禁言操作
        Byte concernStatus = userConcern.getStatus();
        ExecutorService executorService = Executors.newFixedThreadPool(1);
        executorService.execute(()->changeOfSpeakingRightsInTheBroadcastRoom(concernStatus, concernId, userId));
        executorService.shutdown();
    }

    /**
     * 直播间发言权限变更
     * @param status 状态(0取消关注,1关注)
     * @param concernId 被关注人Id
     * @param userId    关注人id
     */
    private void changeOfSpeakingRightsInTheBroadcastRoom(Byte status, Long concernId, Long userId) {
        log.info("触发直播间发言权限变更,status:{},concernId:{},userId:{}", status, concernId, userId);
        Map<String, Object> info = userMapper.inLiveSessionId(concernId);
        if(!CollectionUtils.isEmpty(info)){
            //判断当前直播间的禁言状态是否为粉丝可发言
            Integer cacheObject = redisCache.getCacheObject("live:disableSendMsg:" + info.get("sessionId"));
            if(cacheObject != null && cacheObject == 3){
                if (status == (byte) 1) {
                    tencentCloudIm.bannedGroupMember((String) info.get("roomNum"), 0, Lists.newArrayList(String.valueOf(userId)));
                } else if(status == (byte) 0 ){
                    tencentCloudIm.bannedGroupMember((String) info.get("roomNum"), Integer.MAX_VALUE, Lists.newArrayList(String.valueOf(userId)));
                }
                log.info("触发直播间发言权限变更成功");
            }
        }
    }

    /**
     * 校验用户是否关注该用户
     *
     * @param userId    用户id
     * @param concernId 被关注人Id
     */
    @Override
    public Integer checkUserConcern(Long userId, Long concernId) {
        QueryWrapper<AppUserConcern> wrapper = Wrappers.<AppUserConcern>query()
                .eq("user_Id", userId)
                .eq("concern_id", concernId);
        AppUserConcern userConcern = baseMapper.selectOne(wrapper);
        return null == userConcern || 0 == userConcern.getStatus() ? Constants.YesNoInt.NO : Constants.YesNoInt.YES;
    }

    /**
     * 查询用户关注列表
     *
     * @param baseQuery
     */
    @Override
    public Page<AppUserConcernVO> pageUserConcern(BaseQuery baseQuery) {
        Page<AppUserConcernVO> page = new Page<>(baseQuery.getPageNum(), baseQuery.getPageSize());
        List<AppUserConcernVO> concernList = baseMapper.UserConcernlist(page, baseQuery);
        for (AppUserConcernVO concernVO : concernList) {
            baseQuery.setId(String.valueOf(concernVO.getConcernId()));
            int size = Optional.ofNullable(baseMapper.listUserConcern(page, baseQuery, 1, null)).orElse(Lists.newArrayList()).size();
            concernVO.setFans(size);
            concernVO.setShopId(baseMapper.getShopIdByUserId(concernVO.getConcernId()));
        }
        page.setRecords(concernList);
        return page;
    }

    /**
     * 查询用户粉丝列表
     *
     * @param baseQuery
     */
    @Override
    public Page<AppUserConcernVO> pageUserFans(BaseQuery baseQuery) {
        Page<AppUserConcernVO> page = new Page<>(baseQuery.getPageNum(), baseQuery.getPageSize());
        page.setRecords(baseMapper.listUserConcern(page, baseQuery, 1, null));
        return page;
    }

    /**
     * 查询用户好友列表
     *
     * @param baseQuery
     */
    @Override
    public Page<AppUserConcernVO> pageUserFriend(BaseQuery baseQuery) {

        //查询好友信息
        Page<AppUserConcernVO> page = new Page<>(baseQuery.getPageNum(), baseQuery.getPageSize());
        page.setRecords(userFriendMapper.listFriend(page, baseQuery));
        return page;
    }

    @Override
    public List<AppUserConcern> getUserConcernList(DateTime dateTime) {
        return baseMapper.getUserConcernList(dateTime);
    }

    @Override
    public List<AppUserConcern> getUserConcerns(Long userId) {
        LambdaQueryWrapper<AppUserConcern> queryWrapper=new LambdaQueryWrapper<>();
        queryWrapper.eq(AppUserConcern::getUserId,userId);
        queryWrapper.eq(AppUserConcern::getStatus,1);
        return list(queryWrapper);
    }

    @Override
    public Page<AppUserConcernVO> getFansPage(BaseQuery dto) {
        Page<AppUserConcernVO> page = new Page<>(dto.getPageNum(), dto.getPageSize());
        page.setRecords(baseMapper.getFansPage(page, dto));
        return page;
    }

    @Override
    public Page<AppUserConcernVO> getInteractionUser(BaseQuery dto, String type) {
        dto.setId(String.valueOf(SecurityUtils.getUserId()));
        Page<AppUserConcernVO> page = new Page<>(dto.getPageNum(), dto.getPageSize());

        List<AppUserConcernVO> users = null;
        if("dz".equals(type)){
            users = baseMapper.getLikeVideoUsers(page, dto);
        } else if ("pl".equals(type)) {
            users = baseMapper.getCommentVideoUsers(page, dto);
        } else if ("all".equals(type) && StringUtils.isNotBlank(dto.getName())) {
            users = baseMapper.getAllUserByNikeName(page, dto);
        }
        page.setRecords(users);
        return page;
    }

    @Override
    public Page<AppUserConcernVO> followUser(BaseQuery dto) {
        Page<AppUserConcernVO> page = new Page<>(dto.getPageNum(), dto.getPageSize());
        page.setRecords(baseMapper.followUser(page, dto));
        return page;
    }
}
